<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html><head>
<meta content="uft-8" name="charset">

<title>Is High Quality Software Worth the Cost?</title>
<meta http-equiv="Content-type" content="text/html; charset=UTF-8">
<meta content="summary_large_image" name="twitter:card">

<meta content="16665197" name="twitter:site:id">

<meta content="@martinfowler" name="twitter:site">

<meta content="Is High Quality Software Worth the Cost?" property="og:title">

<meta content="https://martinfowler.com/articles/is-quality-worth-cost.html" property="og:url">

<meta content="We usually perceive that it costs more to get higher quality, but software internal quality actually reduces costs." property="og:description">

<meta content="https://martinfowler.com/articles/is-quality-worth-cost/card.png" property="og:image">

<meta content="martinfowler.com" property="og:site_name">

<meta content="article" property="og:type">

<meta content="2019-05-29" property="og:article:modified_time">

<meta content="width=device-width, initial-scale=1" name="viewport">

<link href="../is-quality-worth-cost.css" rel="stylesheet" type="text/css">
<meta http-equiv="origin-trial" content="AymqwRC7u88Y4JPvfIF2F37QKylC04248hLCdJAsh8xgOfe/dVJPV3XS3wLFca1ZMVOtnBfVjaCMTVudWM//5g4AAAB7eyJvcmlnaW4iOiJodHRwczovL3d3dy5nb29nbGV0YWdtYW5hZ2VyLmNvbTo0NDMiLCJmZWF0dXJlIjoiUHJpdmFjeVNhbmRib3hBZHNBUElzIiwiZXhwaXJ5IjoxNjk1MTY3OTk5LCJpc1RoaXJkUGFydHkiOnRydWV9"><style type="text/css">@font-face { font-family: TencentSans; src: url("moz-extension://7ebec3f3-df69-44bd-9f24-2f7e0d7027ee/static/fonts/TencentSans.woff2"); }</style></head>

<body><header id="banner" style="background-image: url(&quot;/banner.png&quot;); background-repeat: no-repeat">

<div class="name-logo"><a href="https://martinfowler.com/"><img src="../mf-name-white.png"></a></div>
  <div class="search">
    <!-- SiteSearch Google -->
    <form method="GET" action="https://www.google.com/search">
      <input type="hidden" name="ie" value="UTF-8">
      <input type="hidden" name="oe" value="UTF-8">
      <input class="field" type="text" name="q" size="15" maxlength="255">
      <button class="button" type="submit" name="btnG" value=" " title="Search">
      <input type="hidden" name="domains" value="martinfowler.com">
      <input type="hidden" name="sitesearch" value=""> 
      <input type="hidden" name="sitesearch" value="martinfowler.com">
    
  </button></form></div>

<div class="menu-button navmenu-button"><a class="icon icon-bars" href="#navmenu-bottom"></a></div>

<nav class="top-menu">
<ul>
<li><a class="" href="https://refactoring.com/">Refactoring</a></li>

<li><a class="" href="https://martinfowler.com/agile.html">Agile</a></li>

<li><a class="" href="https://martinfowler.com/architecture">Architecture</a></li>

<li><a class="" href="https://martinfowler.com/aboutMe.html">About</a></li>

<li><a class="tw" href="https://www.thoughtworks.com/">Thoughtworks</a></li>

<li><a class="icon icon-rss" href="https://martinfowler.com/feed.atom" title="feed"></a></li>

<li><a class="icon icon-twitter" href="https://www.twitter.com/martinfowler" title="Twitter stream"></a></li>

<li class="icon"><a href="https://toot.thoughtworks.com/@mfowler" title="Mastodon stream"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Pro 6.2.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path d="M433 179.11c0-97.2-63.71-125.7-63.71-125.7-62.52-28.7-228.56-28.4-290.48 0 0 0-63.72 28.5-63.72 125.7 0 115.7-6.6 259.4 105.63 289.1 40.51 10.7 75.32 13 103.33 11.4 50.81-2.8 79.32-18.1 79.32-18.1l-1.7-36.9s-36.31 11.4-77.12 10.1c-40.41-1.4-83-4.4-89.63-54a102.54 102.54 0 0 1-.9-13.9c85.63 20.9 158.65 9.1 178.75 6.7 56.12-6.7 105-41.3 111.23-72.9 9.8-49.8 9-121.5 9-121.5zm-75.12 125.2h-46.63v-114.2c0-49.7-64-51.6-64 6.9v62.5h-46.33V197c0-58.5-64-56.6-64-6.9v114.2H90.19c0-122.1-5.2-147.9 18.41-175 25.9-28.9 79.82-30.8 103.83 6.1l11.6 19.5 11.6-19.5c24.11-37.1 78.12-34.8 103.83-6.1 23.71 27.3 18.4 53 18.4 175z"></path></svg></a></li>
</ul>
</nav>
</header>
<nav id="top-navmenu">
<nav class="navmenu">
<div class="nav-head">  <div class="search">
    <!-- SiteSearch Google -->
    <form method="GET" action="https://www.google.com/search">
      <input type="hidden" name="ie" value="UTF-8">
      <input type="hidden" name="oe" value="UTF-8">
      <input class="field" type="text" name="q" size="15" maxlength="255">
      <button class="button" type="submit" name="btnG" value=" " title="Search">
      <input type="hidden" name="domains" value="martinfowler.com">
      <input type="hidden" name="sitesearch" value=""> 
      <input type="hidden" name="sitesearch" value="martinfowler.com">
    
  </button></form></div>

<div class="closediv">
<span class="close" title="close"></span>
</div>
</div>

<div class="nav-body">
<div class="topics">
<h2>Topics</h2>

<p><a href="https://martinfowler.com/architecture">Architecture</a></p>

<p><a href="https://refactoring.com/">Refactoring</a></p>

<p><a href="https://martinfowler.com/agile.html">Agile</a></p>

<p><a href="https://martinfowler.com/delivery.html">Delivery</a></p>

<p><a href="https://martinfowler.com/microservices">Microservices</a></p>

<p><a href="https://martinfowler.com/data">Data</a></p>

<p><a href="https://martinfowler.com/testing">Testing</a></p>

<p><a href="https://martinfowler.com/dsl.html">DSL</a></p>
</div>

<div class="about">
<h2>about me</h2>

<p><a href="https://martinfowler.com/aboutMe.html">About</a></p>

<p><a href="https://martinfowler.com/books">Books</a></p>

<p><a href="https://martinfowler.com/faq.html">FAQ</a></p>
</div>

<div class="content">
<h2>content</h2>

<p><a href="https://martinfowler.com/videos.html">Videos</a></p>

<p><a href="https://martinfowler.com/tags">Content Index</a></p>

<p><a href="https://martinfowler.com/articles/eurogames">Board Games</a></p>

<p><a href="https://martinfowler.com/photos">Photography</a></p>
</div>

<div class="tw">
<h2>Thoughtworks</h2>

<p><a href="https://thoughtworks.com/insights">Insights</a></p>

<p><a href="https://thoughtworks.com/careers">Careers</a></p>

<p><a href="https://thoughtworks.com/products">Products</a></p>
</div>

<div class="feeds">
<h2>follow</h2>

<p><a href="https://www.twitter.com/martinfowler">Twitter</a></p>

<p><a href="https://martinfowler.com/feed.atom">RSS</a></p>

<p><a href="https://toot.thoughtworks.com/@mfowler">Mastodon</a></p>
</div>
</div>
</nav>
</nav>

<nav id="toc-dropdown">
<button class="dropdown-button">
<h2>Table of Contents</h2>
</button>

<div class="hidden" id="dropdownLinks">
<ul>
<li><a href="#top">Top</a></li>

<li><a href="#WeAreUsedToATrade-offBetweenQualityAndCost">We are used to a trade-off between quality and cost</a></li>
<li><a href="#WeAreUsedToATrade-offBetweenQualityAndCost">We are used to a trade-off between quality and cost</a></li>

<li><a href="#SoftwareQualityMeansManyThings">Software quality means many things</a></li>

<li><a href="#AtFirstGlanceInternalQualityDoesNotMatterToCustomers">At first glance, internal quality does not matter to customers</a></li>

<li><a href="#InternalQualityMakesItEasierToEnhanceSoftware">Internal quality makes it easier to enhance software</a></li>

<li><a href="#CustomersDoCareThatNewFeaturesComeQuickly">Customers do care that new features come quickly</a></li>

<li><a href="#VisualizingTheImpactOfInternalQuality">Visualizing the impact of internal quality</a></li>

<li><a href="#EvenTheBestTeamsCreateCruft">Even the best teams create cruft</a></li>

<li><a href="#HighQualitySoftwareIsCheaperToProduce">High quality software is cheaper to produce</a></li>
</ul>

<h3>Sidebars</h3>

<ul>
<li><a href="#DoraStudiesOnEliteTeams">Dora studies on elite teams</a></li>
</ul>
</div>
</nav>

<main>
<h1>Is High Quality Software Worth the Cost? 高质量软件是否值得投入成本？</h1>

<section class="frontMatter">
<p class="date">29 May 2019</p>
<hr>
<div class="front-grid">
<div class="author-list">
<div class="author">
<div class="photo"><a href="https://martinfowler.com/"><img alt="Photo of Martin Fowler" src="../mf.jpg" width="80"></a></div>

<address class="name"><a href="https://martinfowler.com/" rel="author">Martin Fowler</a></address>
</div>
</div>

<div class="tags">
<p class="tag-link"><a href="https://martinfowler.com/tags/programming%20style.html">programming style</a></p>
<p class="tag-link"><a href="https://martinfowler.com/tags/programming%20style.html">编程风格</a></p>

<p class="tag-link"><a href="https://martinfowler.com/tags/productivity.html">productivity</a></p>
<p class="tag-link"><a href="https://martinfowler.com/tags/productivity.html">生产力</a></p>

<p class="tag-link"><a href="https://martinfowler.com/tags/project%20planning.html">project planning</a></p>
<p class="tag-link"><a href="https://martinfowler.com/tags/project%20planning.html">项目规划</a></p>

<p class="tag-link"><a href="https://martinfowler.com/tags/technical%20debt.html">technical debt</a></p>
<p class="tag-link"><a href="https://martinfowler.com/tags/technical%20debt.html">技术债务</a></p>
</div>

<div class="contents">
<h2>Contents</h2>

<ul>
<li><a href="#WeAreUsedToATrade-offBetweenQualityAndCost">We are used to a trade-off between quality and cost</a></li>
<li><a href="#WeAreUsedToATrade-offBetweenQualityAndCost">我们习惯于在质量和成本之间进行权衡。</a></li>

<li><a href="#SoftwareQualityMeansManyThings">Software quality means many things</a></li>
<li><a href="#SoftwareQualityMeansManyThings">软件质量代表很多东西</a></li>

<li><a href="#AtFirstGlanceInternalQualityDoesNotMatterToCustomers">At first glance, internal quality does not matter to customers</a></li>
<li><a href="#AtFirstGlanceInternalQualityDoesNotMatterToCustomers">乍一看，内部质量对客户并不重要。</a></li>

<li><a href="#InternalQualityMakesItEasierToEnhanceSoftware">Internal quality makes it easier to enhance software</a></li>
<li><a href="#InternalQualityMakesItEasierToEnhanceSoftware">内部质量使得增强软件变得更加容易。</a></li>

<li><a href="#CustomersDoCareThatNewFeaturesComeQuickly">Customers do care that new features come quickly</a></li>
<li><a href="#CustomersDoCareThatNewFeaturesComeQuickly">客户确实关心新功能能否快速推出。</a></li>

<li><a href="#VisualizingTheImpactOfInternalQuality">Visualizing the impact of internal quality</a></li>
<li><a href="#VisualizingTheImpactOfInternalQuality">把内部质量影响进行可视化</a></li>

<li><a href="#EvenTheBestTeamsCreateCruft">Even the best teams create cruft</a></li>
<li><a href="#EvenTheBestTeamsCreateCruft">即使是最优秀的团队也会产生垃圾代码。</a></li>

<li><a href="#HighQualitySoftwareIsCheaperToProduce">High quality software is cheaper to produce</a></li>
<li><a href="#HighQualitySoftwareIsCheaperToProduce">高质量软件的生产成本更低。</a></li>
</ul>

<h3>Sidebars</h3>

<ul>
<li><a href="#DoraStudiesOnEliteTeams">Dora studies on elite teams</a></li>
<li><a href="#DoraStudiesOnEliteTeams">Dora对精英团队的研究。</a></li>
</ul>
</div>
</div>
<hr></section>

<div class="paperBody shallow">
<p>A common debate in software development projects is between spending time
    on improving the quality of the software versus concentrating on releasing
    more valuable features. Usually the pressure to deliver functionality
    dominates the discussion, leading many developers to complain that they
    don't have time to work on architecture and code quality.</p>

<p>在软件开发项目中，一个常见的辩论是: 在提高软件质量, 与集中精力发布更有价值的功能, 之间进行选择。
    通常，交付功能的需求主导着讨论，导致许多开发者抱怨他们没有时间去关注架构和代码质量。</p>

<p><a href="https://en.wikipedia.org/wiki/Betteridge%27s_law_of_headlines">Betteridge's Law of headlines</a> is an
    adage that says any article with a headline or title that ends in a question
    mark can be summarized by "no". Those that know me would not doubt my desire
    to subvert such a law. But this article goes further than that - it subverts
    the question itself. The question assumes the common trade-off between
    quality and cost. With this article I'll explain that this trade-off does
    not apply to software - that high quality software is actually cheaper to
    produce.</p>

<p><a href="https://en.wikipedia.org/wiki/Betteridge%27s_law_of_headlines">Betteridge 标题定律</a> 是一条格言，
    它说任何以问号结尾的标题或标题的文章都可以用“不”来概括。
    那些了解我的人不会怀疑我颠覆这条定律的愿望。
    但这篇文章走得更远，它颠覆了问题本身。
    这个问题假定了质量和成本之间的常见权衡。
    通过这篇文章，我将解释这种权衡在软件中并不适用——高质量软件实际上更便宜。
</p>

<p>Although most of my writing is aimed at professional software developers,
    for this article I'm not going to assume any knowledge of the mechanics of
    software development. My hope is that this is an article that can be
    valuable to anyone involved with thinking about software efforts,
    particularly those, such as business leaders, that act as customers of
    software development teams.</p>
    
<p>尽管我大部分写作都是针对专业软件开发人员，
    但在这篇文章中，我不会假设读者对软件开发的机制有任何了解。
    我的希望是，这篇文章对那些参与思考软件工作的人都有价值，
    特别是那些作为软件开发团队客户的企业领导者。
</p>

<section id="WeAreUsedToATrade-offBetweenQualityAndCost">
<h2>We are used to a trade-off between quality and cost 我们习惯于在质量和成本之间进行权衡。</h2>

<p>As I mentioned in the opening, we are all used to a trade-off between
      quality and cost. When I replace my smart phone, I can choose a
      more expensive model with faster processor, better screen, and more
      memory. Or I can give up some of those qualities to pay less money. It's
      not an absolute rule, sometimes we can get bargains where a high quality
      good is cheaper. More often we have different values to quality - some people
      don't really notice how one screen is nicer than another. But the
      assumption is true most of the time, higher quality usually costs more.
      </p>
  
<p>正如我在开头提到的，我们都习惯于在质量和成本之间进行权衡。
    当我更换我的智能手机时，我可以选择一个更昂贵、处理器更快、屏幕更好、内存更大的型号。
    或者，我可以放弃一些这些品质，以支付更少的钱。
    这并不是一条绝对的规则，有时我们可以找到一些高质量商品价格更低的优惠。
    更常见的是，我们对于质量有不同的价值观——有些人真的不怎么注意到一个屏幕比另一个屏幕更好。
    但这个假设在大多数时候是正确的，更高的质量通常成本更高。
</p>
</section>

<section id="SoftwareQualityMeansManyThings">
<h2>Software quality means many things</h2>

<p>If I'm going to talk about quality for software, I need to explain what
      that is. Here lies the first complication - there are many things that can
      count as quality for software. I can consider the user-interface: does it easily
      lead me through the tasks I need to do, making me more efficient and
      removing frustrations? I can consider its reliability: does it contain
      defects that cause errors and frustration? Another aspect is its
      architecture: is the source code divided into clear modules, so that
      programmers can easily find and understand which bit of the code they need
      to work on this week?</p>

<p>如果要谈论软件的质量，我需要先解释什么是质量。
    这里出现了第一个复杂问题——对于软件来说，有许多可以被认为是质量的东西。
    我可以考虑用户界面：它是否轻松地带我完成我需要做的任务，使我更有效率，减少挫折感？
    我可以考虑它的可靠性：它是否包含导致错误和挫折的缺陷？
    另一个方面是它的架构：源代码是否被清晰地划分为模块，以便程序员可以轻松地找到并理解他们本周需要工作的代码部分？
</p>

<p>These three examples of quality are not an exhaustive list, but they
      are enough to illustrate an important point. If I'm a customer, or user, of
      the software, I don't appreciate some of the things we'd refer to as
      quality. A user can tell if the user-interface is good. An
      executive can tell if the software is making her staff more efficient at
      their work. Users and customers will notice defects, particularly should
      they corrupt data or render the system inoperative for a while. But
      customers and users cannot perceive the architecture of the software.</p>


<p>这三个质量示例并不是一个详尽的列表，但它们足以说明一个重要观点。
    如果我是一个软件的客户或用户，我不欣赏我们称之为质量的这些东西。
    用户可以判断出用户界面的好坏。
    一个高管可以判断出软件是否使她的员工在工作中更加高效。
    用户和客户会注意到缺陷，特别是在它们损坏数据或使系统暂时无法使用的情况下。
    但是，客户和用户无法感知软件的架构。
</p>


<p>I thus divide software quality attributes into <b>external</b>
      (such as the UI and defects) and <b>internal</b> (architecture). The
      distinction is that users and customers can see what makes a software
      product have high external quality, but cannot tell the difference between
      higher or lower internal quality.</p>


<p>因此，我将软件质量属性分为 <b>外部</b>（如UI和缺陷）和 <b>内部</b>（架构）。
    区别在于，用户和客户可以看到使软件产品具有高外部质量的因素，但却无法区分内部质量的高低。</p>
</section>

<section id="AtFirstGlanceInternalQualityDoesNotMatterToCustomers">
<h2>At first glance, internal quality does not matter to customers</h2>

<p>Since internal quality isn't something that customers or users can see
      - does it matter? Let's imagine Rebecca and I write an application to
      track and predict flight delays. Both our applications do the same
      essential function, both have equally elegant user interfaces, and both
      have hardly any defects. The only difference is that her internal source
      code is neatly organized, while mine is a tangled mess. There is one other
      difference: I sell mine for $6 and she sells hers for $10.</p>

<p>由于内部质量是客户或用户无法看到的——那么它重要吗？
    让我们想象Rebecca和我编写了一个应用程序来跟踪和预测航班延误。
    我们的应用程序都执行了相同的基本功能，用户界面都同样优雅，而且几乎都没有缺陷。
    唯一的区别是她的内部源代码组织得井井有条，而我的则是一团糟。
    还有一个区别：我以6美元的价格出售我的应用程序，而她以10美元的价格出售她的。
</p>

<p>Since a customer never sees this source code, and it doesn't affect the
      operation of the app, why would anyone pay an extra $4 for Rebecca's software?
      Put more generally this should mean that it isn't worth paying more money
      for higher internal quality.</p>

<p>由于客户从未看到这段源代码，而且它不影响应用程序的运行，为什么有人会为Rebecca的软件多支付4美元呢？
    更广泛地说，这应该意味着为更高的内部质量支付更多的钱是不值得的。
</p>

<p>Another way I put this is that it makes sense to trade cost for
      external quality but it makes no sense to trade cost for internal quality.
      A user can judge whether they want to pay more to get a better user
      interface, since they can assess whether the user interface is sufficiently
      nicer to be worth the extra money. But a user can't see the internal
      modular structure of the software, let alone judge that it's better. Why pay
      more for something that has no effect?
      Since that's the case - why should
      any software developer put their time and effort into improving the
      internal quality of their work?</p>

<p>另一种说法是，从成本上讲，用外部质量换取成本是有意义的，但从成本上讲，用内部质量换取成本是没有意义的。
    用户可以判断他们是否愿意为更好的用户界面支付更多费用，因为他们可以评估用户界面是否足够好，值得额外的钱。
    但是，用户无法看到软件的内部模块结构，更不用说判断它是否更好了。
    为什么要为没有任何效果的东西支付更多费用呢？
    既然如此，为什么任何软件开发者应该把时间和精力投入到提高他们工作的内部质量上呢？
</p>
</section>

<section id="InternalQualityMakesItEasierToEnhanceSoftware">
<h2>Internal quality makes it easier to enhance software</h2>

<p>So why is it that software developers make an issue out of internal
      quality? Programmers spend most of their time modifying code. Even in a
      new system, almost all programming is done in the context of an existing
      code base. When I want to add a new feature to the software, my first task
      is to figure out how this feature fits into the flow of the existing
      application. I then need to change that flow to let my feature fit in. I
      often need to use data that's already in the application, so I need to
      understand what the data represents, how it relates to the data around it,
      and what data I may need to add for my new feature.</p>

<p>那么，为什么软件开发者会将内部质量作为一个问题呢？
    程序员大部分时间都在修改代码。
    即使在一个新的系统中，几乎所有的编程都是在现有的代码库的上下文中完成的。
    当我想要向软件中添加一个新功能时，我的第一个任务是弄清楚这个功能如何适合现有的应用程序流程。
    然后我需要改变这个流程，让我的功能能够融入其中。
    我经常需要使用应用程序中已经存在的数据，所以我要理解数据代表什么，它与周围数据的关系，
    以及我可能需要为我的新功能添加什么数据。
</p>

<p>All of this is about me understanding the existing code. But it's very
      easy for software to be hard to understand. Logic can get tangled, the
      data can be hard to follow, the names used to refer to things may have
      made sense to Tony six months ago, but are as mysterious to me as his
      reasons for leaving the company. All of these are forms of what
      developers refer to as <b>cruft</b> - the difference between the current code
      and how it would ideally be.</p>

<p>所有这些都与我要理解现有代码有关。
    但软件很容易变得难以理解。
    逻辑可能会变得混乱，数据可能难以追踪，用来指代事物的名称可能在六个月前对Tony有意义，但现在对我来说就像他离开公司的理由一样神秘。
    所有这些都是开发人员所说的<b>垃圾代码</b>（cruft）的形式
    ——当前代码和理想代码之间的差异。
</p>

<aside class="sidebar">
<p>A common metaphor for cruft is <a href="https://martinfowler.com/bliki/TechnicalDebt.html">Technical Debt</a>. The
        extra cost on adding features is like paying interest. Cleaning up the
        cruft is like paying down the principal. While it's a helpful metaphor,
        it does encourage many to believe cruft is much easier to measure and
        control than it is in practice.</p>

<p>垃圾代码的一个常见隐喻是 <a href="./bliki/TechnicalDebt.html">技术债务</a>。
    添加功能的额外成本就像支付利息。
    清理垃圾代码就像偿还本金。
    虽然这是一个有帮助的隐喻，但它确实使许多人相信垃圾代码在实践中比实际更容易衡量和控制。
</p>

<div class="photo "><span class="img-link"><a href="https://martinfowler.com/bliki/TechnicalDebt.html"><img src="../sketch.png"></a></span>
<p class="photoCaption"></p>
</div>
</aside>

<p>One of the primary features of internal quality is making it easier for
      me to figure out how the application works so I can see how to add things.
      If the software is nicely divided into separate modules, I don't have to
      read all 500,000 lines of code, I can quickly find a few hundred lines in
      a couple of modules. If we've put the effort into clear naming, I can
      quickly understand what the various part of the code does without having
      to puzzle through the details. If the data sensibly follows the language
      and structure of the underlying business, I can easily understand how it
      correlates to the request I'm getting from the customer service reps. 
      Cruft adds to the time it take for me to understand how to make a change,
      and also increases the chance that I'll make a mistake. If I spot my mistakes, then
      there's more time lost as I have to understand what the fault is and how to
      fix it. If I don't spot them, then we get production defects, and more time
      spend fixing things later.</p>

<p>内部质量的一个主要特征是使我更容易理解应用程序的工作方式，从而看到如何添加功能。
    如果软件被合理地划分为独立的模块，我不必阅读所有500,000行代码，我可以快速找到几个模块中的几百行代码。
    如果我们努力使用清晰的命名，我可以快速理解代码的各个部分做什么，而不必费力理解细节。
    如果数据合理地遵循底层业务的语言和结构，我可以轻松理解它与客户服务的请求如何相关。
    垃圾代码增加了我理解如何进行更改所需的时间，也增加了我犯错的机会。
    如果我发现了我的错误，那么我需要花更多时间来理解故障是什么以及如何修复它。
    如果我没有发现它们，那么我们会在后期花费更多时间来修复生产缺陷。
</p>

<p>My changes also affect the future. I may see a quick way to put in this
      feature, but it's a route that goes against the modular structure of the
      program, adding cruft. If I take that path, I'll make it quicker for me today, but slow
      down everyone else who has to deal with this code in future weeks and
      months. Once other members of the team make the same decision, an easy to
      modify application can quickly accumulate cruft to the point where every little
      change takes many weeks of effort.</p>

<p>我的更改还会影响未来。
我可能会看到一个快速加入这个功能的方法，但这会违反程序的模块化结构，增加垃圾代码。
如果我选择这条路，我今天会更快，但会在未来的几周和几个月里减慢其他所有人的速度，他们必须处理这段代码。
一旦团队的其他成员做出同样的决定，一个易于修改的应用程序可以迅速积累垃圾代码，
以至于每一次小小的更改都需要花费几周的努力。
</p>

</section>

<section id="CustomersDoCareThatNewFeaturesComeQuickly">
<h2>Customers do care that new features come quickly </h2>

<p>Here we see a clue of why internal quality does matter to users and
      customers. Better internal quality makes adding new features easier,
      therefore quicker and cheaper. Rebecca and I may have the same application
      now, but in the next few months Rebecca's high internal quality allows her
      to add new features every week, while I'm stuck trying chop through the
      cruft to get just a single new feature out. I can't compete with Rebecca's
      speed, and soon her software is far more featureful than mine. Then all my customers
      delete my app, and get Rebecca's instead, even as she's able to increase
      her price.</p>

<p>在这里，我们看到了为什么内部质量对用户和客户来说很重要的线索。
    更好的内部质量使得添加新功能变得更容易，因此更快、更便宜。
    Rebecca和我现在可能有相同的应用程序，
    但在接下来的几个月里，Rebecca的高内部质量让她每周都能添加新功能，
    而我要努力砍掉垃圾代码，才能推出一个新功能。
    我无法与Rebecca的速度竞争，很快她的软件功能就远远超过了我。
    然后，我的所有客户都删除了我的应用程序，转而使用Rebecca的，即使她能够提高价格。
</p>

<div class="figure " id="cruft-impact.png"><img src="../cruft-impact.png">
<p class="photoCaption"></p>
</div>

<div class="clear"></div>
</section>

<section id="VisualizingTheImpactOfInternalQuality">
<h2>Visualizing the impact of internal quality</h2>

<p>The fundamental role of internal quality is
      that it lowers the cost of future change. But there is some extra effort
      required to write good software, which does impose some cost in the short term.</p>

<p>内部质量的基本作用是降低未来变更的成本。
    但是，编写优质软件需要一些额外的努力，这确实会在短期内增加一些成本。
</p>

<p>A way of visualizing this is with the following pseudo-graph, where I
      plot the cumulative functionality of software versus the time (and thus
      cost) to produce it. For most software efforts, the curve looks something
      like this.</p>

<p>一种可视化这种关系的方法是使用以下伪图形，
    其中我绘制了软件的累积功能与时间（从而成本）的关系。
    对于大多数软件项目，曲线看起来像这样。
</p>

<div class="figure " id="poor.png"><img src="../poor.png">
<p class="photoCaption"></p>
</div>

<div class="clear"></div>

<p>This is what happens with poor internal quality. Progress is rapid
      initially, but as time goes on it gets harder to add new features. Even
      small changes require programmers to understand large areas of code, code
      that's difficult to understand. When they make changes, unexpected
      breakages occur, leading to long test times and defects that need to be
      fixed.</p>

<p>这是内部质量差时发生的情况。
    起初进展迅速，但随着时间推移，添加新功能变得越来越困难。
    即使是很小的更改也需要程序员理解大量代码，这些代码难以理解。
    当他们进行更改时，意外的故障会发生，导致漫长的测试时间和需要修复的缺陷。
</p>

<p>Concentrating on high internal quality is about reducing that drop off
      in productivity. Indeed some products see an opposite effect, where
      developers can accelerate as new features can be easily built by making
      use of prior work. This happy situation is a rarer case, as it requires a
      skilled and disciplined team to make it happen. But we do occasionally see
      it.</p>

<p>专注于高内部质量是为了减少生产力的下降。
    实际上，一些产品看到了相反的效果，其中开发者可以通过利用之前的工作轻松构建新功能，从而加速开发。
    这种理想的情况更为罕见，因为它需要一个技能娴熟且自律的团队来实现。
    但我们偶尔确实能看到这种情况。
</p>

<div class="figure " id="both.png"><img src="../both.png">
<p class="photoCaption"></p>
</div>

<div class="clear"></div>

<p>The subtlety here is that there is a period where the low internal
      quality is more productive than the high track. During this time there is
      some kind of trade-off between quality and cost. The question, of course,
      is: how long is that period before the lines cross?</p>
      
<p>这里的微妙之处在于，在一段时间内，低内部质量比高标准的路径更有生产力。
    在这段时间内，质量和成本之间存在某种权衡。
    当然，问题是：在两条线交叉之前，这段时间有多长？
</p>

<aside>
<div class="article-card">
<h3><a href="https://martinfowler.com/bliki/CannotMeasureProductivity.html">Cannot Measure Productivity</a></h3>

<div class="card-body">
<p class="card-image"><img src=""></p>

<p>We see so much emotional discussion about software process,
design practices and the like. Many of these arguments are impossible
to resolve because the software industry lacks the ability to measure
some of the basic elements of the effectiveness of software
development. In particular we have no way of reasonably measuring
productivity.</p>

<p>我们在软件过程、设计实践等方面看到了很多情绪化的讨论。
许多这些争论无法解决，因为软件行业缺乏衡量软件开发有效性的某些基本元素的能力。
特别是，我们无法合理地衡量生产力。
</p>

<div class="meta">
<p class="credits">by Martin Fowler</p>

<p class="date">29 Aug 2003</p>

<p class="more"><a href="https://martinfowler.com/bliki/CannotMeasureProductivity.html">Read more…</a></p>

<p class="type bliki">bliki</p>

<p class="tags"> <span class="tag-link"><a href="https://martinfowler.com/tags/productivity.html">productivity</a></span> <span class="tag-link"><a href="https://martinfowler.com/tags/metrics.html">metrics</a></span> <span class="tag-link"><a href="https://martinfowler.com/tags/project%20planning.html">project planning</a></span> <span class="tag-link"><a href="https://martinfowler.com/tags/estimation.html">estimation</a></span> </p>
</div>
</div>
</div>
</aside>

<p>At this point we run into why this is a pseudo-graph. There is no way
      of measuring the functionality delivered by a software team. This
      inability to measure output, and thus productivity, makes it impossible to
      put solid numbers on the consequences of low internal quality (which is
      also difficult to measure). An inability to measure output is pretty
      common among professional work - how do we measure the productivity of
      lawyers or doctors?</p>
  
<p>在这里，我们遇到了为什么这是一个伪图形的原因。
    没有办法衡量软件团队交付的功能性。
    这种无法衡量产出（因此生产力）的能力使得无法为低内部质量的后果（这也难以衡量）奠定坚实的基础。
    无法衡量产出在专业工作中相当常见——我们如何衡量律师或医生的生产力？
</p>

<p>The way I assess where lines cross is by canvassing the opinion of
      skilled developers that I know. And the answer surprises a lot of folks.
      Developers find poor quality code significantly slows them down within a
      few weeks. So there's not much runway where the trade-off between internal
      quality and cost applies. Even small software efforts benefit from
      attention to good software practices, certainly something I can attest
      from my experience.</p>
      
<p>我评估线条交叉的方法是通过咨询我认识的熟练开发者。
    这个答案让很多人感到惊讶。
    开发者发现低质量代码会在几周内显著减慢他们的速度。
    所以，内部质量和成本之间的权衡适用的时间并不长。
    即使是小型软件项目，也可以从关注好的软件实践中受益，这我完全可以证明。
</p>

</section>

<section id="EvenTheBestTeamsCreateCruft">
<h2>Even the best teams create cruft</h2>

<p>Many non-developers tend to think of cruft as something that only
      occurs when development teams are careless and make errors, but even the
      finest teams will inevitably create some cruft as they work.</p>

<p>许多非开发者倾向于认为垃圾代码只是当开发团队粗心大意和犯错时才会发生，
    但即使是最好的团队在工作的过程中也必然会不可避免地产生一些垃圾代码。
</p>

<p>I like to illustrate this point with a tale of when I was chatting with
      one of our best technical team leads. He'd just finished a project that
      was widely considered to be a great success. The client was happy with the
      delivered system, both in terms of its capabilities and its construction
      time and cost. Our people were positive about the experience of working on
      the project. The tech lead was broadly happy but confessed that the
      architecture of the system wasn't that good. I reacted with "how could
      that be - you're one of our best architects?" His reply is one familiar to
      any experienced software architect: "we made good decisions, but only now
      do we understand how we should have built it".</p>

<p>我喜欢用一个故事来阐明这个观点，这个故事发生在我和我们的一个最佳技术团队领导聊天的时候。
    他刚完成一个项目，该项目被广泛认为是巨大的成功。
    客户对交付的系统既满意其功能，也满意其构建时间和成本。
    我们的员工对在该项目上工作的经历持积极态度。
    技术领导总体上很满意，但承认系统的架构并不是那么好。
    我对他说：“这怎么可能——你可是我们最好的架构师之一啊？”
    他回答的是任何有经验的软件架构师都熟悉的答复：
    “我们做出了好的决策，但只有现在我们才明白应该如何构建它。”
</p>

<p>Many people, including more than a few in the software industry, liken
      building software to constructing cathedrals or skyscrapers - after all
      why do we use "architect" for senior programmers? But building software
      exists in a world of uncertainty unknown to the physical world. Software's
      customers have only a rough idea of what features they need in a product
      and learn more as the software is built - particularly once early versions
      are released to their users. The building blocks of software development -
      languages, libraries, and platforms - change significantly every few
      years. The equivalent in the physical world would be that customers
      usually add new floors and change the floor-plan once half the building is
      built and occupied, while the fundamental properties of concrete change
      every other year.</p>

<p>许多人，包括软件行业中的许多人，将建造软件比作建造大教堂或摩天大楼
    ——毕竟，为什么我们用“架构师”来称呼高级程序员呢？
    但建造软件存在于物理世界未知的不确定性世界中。
    软件的客户对他们需要在产品中拥有的功能只有一个大致的概念，并且随着软件的构建而了解得更多
    ——特别是一旦早期版本被发布给他们的用户。
    软件开发的基石——语言、库和平台——每几年就会发生显著的变化。
    在物理世界中，这相当于客户通常在建筑物建成一半并入住后添加新楼层并改变平面图，
    而混凝土的基本属性每两年就会改变一次。
</p>

<aside class="sidebar" id="DoraStudiesOnEliteTeams">
<h2>Dora studies on elite teams</h2>

<p>The choice between quality and speed isn't the only choice in software
    development that makes intuitive sense, but is wrong. There is also a strong
    thread of thought that says there is a <a href="https://martinfowler.com/bliki/BimodalIT.html">Bimodal</a> choice
    between fast development, with frequent updates to a system, and reliable
    systems that don't break in production. That this is a false choice is
    proven by the careful scientific work in the <a href="https://martinfowler.com/bliki/StateOfDevOpsReport.html">State Of Dev Ops Report</a>. </p>

<p>在软件开发中，质量与速度之间的选择并不是唯一一个在直觉上看似合理但实际上错误的选择。
    还有一种强烈的观点认为，快速开发，频繁更新系统，
    与可靠系统，在生产中不中断，之间存在一个<a href="./bliki/BimodalIT.html">双模态</a>选择。
    这一选择被<a href="./bliki/StateOfDevOpsReport.html">《Dev Ops状态报告》</a>中仔细的科学研究证明是错误的。
</p>

<p>For several years they have used statistical
    analysis of surveys to tease out the practices of high performing software
    teams. Their work has shown that elite software teams update production code
    many times a day, pushing code changes from development to production in
    less than an hour. As they do this, their change failure rate is
    significantly lower than slower organizations so they recover from errors much
    more quickly. Furthermore, such elite software delivery organizations are
    correlated with higher organizational performance.</p>


<p>多年来，他们一直使用调查的统计分析来揭示高性能软件团队的做法。
    他们的工作表明，精英软件团队每天多次更新生产代码，将代码更改从开发推送到生产不到一个小时。
    在这个过程中，他们的更改失败率明显低于较慢的组织，因此他们能够更快地从错误中恢复。
    此外，这样的精英软件交付组织与更高的组织绩效相关联。
</p>
    
</aside>

<p>Given this level of change, software projects are always creating
      something novel. We hardly ever find ourselves working on a
      well-understood problem that's been solved before. Naturally we learn most
      about the problem as we're building the solution, so it's common for me to
      hear that teams only really best understand what the architecture of their
      software should be after they've spent a year or so building it. Even the
      best teams will have cruft in their software.</p>
      
<p>考虑到这种变更水平，软件项目总是在创造新事物。
    我们很少发现自己正在处理一个已经解决过、被充分理解的问题。
    自然地，我们会在构建解决方案的过程中了解到更多关于问题，
    所以我很常见到团队在花费一年或更长时间构建后，才真正明白他们的软件架构应该是怎样的。
    即使是最优秀的团队，他们的软件中也都会有垃圾代码。
</p>

<p>The difference is that the best teams both create much less cruft but
      also remove enough of the cruft they do create that they can continue to
      add features quickly. They spend time creating automated tests so that
      they can surface problems quickly and spend less time removing bugs. They
      refactor frequently so that they can remove cruft before it builds up
      enough to get in the way. Continuous integration minimizes cruft
      building up due to team members working at cross-purposes. A common
      metaphor is that it's like cleaning up work surfaces and equipment in the
      kitchen. You can't not make things dirty when you cook, but if you don't
      clean things quickly, muck dries up, is harder to remove, and all the
      dirty stuff gets in the way of cooking the next dish.</p>

<p>区别在于，最好的团队不仅创建的垃圾代码更少，
    而且还会移除他们创建的足够多的垃圾代码，这样他们就可以快速地继续添加功能。
    他们会花时间创建自动化测试，这样他们就可以快速地发现问题，并花更少的时间去除错误。
    他们经常重构，这样他们就可以在垃圾代码积累到妨碍之前将其移除。
    持续集成最小化了由于团队成员工作目标不一致而导致的垃圾代码积累。
    一个常见的比喻是，这就像在厨房里清洁工作台面和设备。
    当你做饭时，不可能不弄脏东西，
    但如果你不快速清理，污垢会干燥、更难去除，所有脏东西都会阻碍下一道菜的烹饪。
</p>
</section>

<section id="HighQualitySoftwareIsCheaperToProduce">
<h2>High quality software is cheaper to produce</h2>

<p>Summing all of this up:</p>

<p>总结以上所有内容：</p>

<ul>
<li>Neglecting internal quality leads to rapid build up of cruft</li>

<li>忽视内部质量会导致垃圾代码的快速积累。</li>

<li>This cruft slows down feature development</li>

<li>这层垃圾代码减慢了功能开发的速度。</li>

<li>Even a great team produces cruft, but by keeping internal quality
        high, is able to keep it under control</li>

<li>即使是一个伟大的团队也会产生垃圾代码，但通过保持高内部质量，它们能够控制垃圾代码数量。</li>

<li>High internal quality keeps cruft to a minimum, allowing a team to
        add features with less effort, time, and cost.</li>

<li>高内部质量将垃圾代码控制在最小限度，
    使得团队能够以更少的努力、时间和成本添加新功能。</li>
</ul>

<p>Sadly, software developers usually don't do a good job of explaining
      this situation. Countless times I've talked to development teams who say
      "they (management) won't let us write good quality code because it takes
      too long". Developers often justify attention to quality by justifying
      through the need for proper professionalism. But this moralistic
      argument implies that this quality comes at a cost - dooming their
      argument. The annoying thing is that the resulting crufty code both makes
      developers' lives harder, and costs the customer money. When thinking about
      internal quality, I stress that we should only approach it as an economic argument.
      High internal quality reduces the cost of future features, meaning that
      putting the time into writing good code actually reduces cost.</p>

<p>不幸的是，软件开发者通常不擅长解释这种状况。
    无数次我曾与开发团队交谈，他们说：“他们（管理层）不让我们编写高质量的代码，因为太花时间了”。
    开发者经常通过职业道德的需要来证明关注质量的重要性。
    但这种道德主义论点意味着质量是有成本的——注定他们的论点失败。
    恼人的是，结果的垃圾代码既让开发者的生活更艰难，也让客户付出金钱的代价。
    当考虑到内部质量时，我强调我们应该只将其视为一个经济问题。
    高内部质量减少了未来功能的成本，这意味着投入时间编写优质代码实际上可以降低成本。
</p>

<p>This is why the question that heads this article misses the point. The
      "cost" of high internal quality software is negative. The usual trade-off
      between cost and quality, one that we are used to for most decisions in
      our life, does not make sense with the internal quality of software. (It
      does for external quality, such as a carefully crafted user-experience.)
      Because the relationship between cost and internal quality is an unusual
      and counter-intuitive relationship, it's usually hard to absorb. But
      understanding it is critical to developing software at maximum
      efficiency.</p>

<p>这就是为什么这篇文章的标题问题错过了重点。
    “高质量内部软件的成本”是一个负数。
    我们生活中大多数决策中常见的成本和质量之间的权衡，对于软件的内部质量来说是没有意义的。
    （它适用于外部质量，比如精心设计的用户体验。）
    因为成本和内部质量之间的关系是不常见和反直觉的，
    所以通常很难接受。
    但理解它是以最大效率开发软件的关键。
</p>

</section>

<hr class="bodySep">
</div>

<div class="appendix">
<section id="MeasuringTheEffectsOfLowInternalQuality">
<h2>Measuring the effects of low internal quality</h2>

<p><i>(added: 2024-01-29)</i></p>

<p>As I mentioned above, we don't really know how to measure internal
      quality, or productivity, and so it's difficult to get quantifiable
      evidence for the importance of internal quality. However in recent years,
      there has been increasing efforts to try.</p>

<p>如我上文所述，我们实际上不知道如何衡量内部质量或生产力，
    因此很难获得内部质量重要性的量化证据。
    然而，在最近几年，人们越来越努力尝试去解决这个问题。
</p>

<p>One particularly interesting paper that I've come across is this study
      from <a href="https://arxiv.org/abs/2203.04374">Adam Tornhill and Markus Borg</a>.
      They use their proprietary tool, CodeScene, to determine the health level
      of files in 39 proprietary code bases. They found that resolving issues in
      low quality took more than twice as long as doing so in high quality code,
      and that low quality code had 15 times higher defect density.</p>

<p>我查阅过的一篇特别有趣的论文是来自<a href="https://arxiv.org/abs/2203.04374">Adam Tornhill和Markus Borg</a>的研究。
    他们使用他们专有的工具CodeScene来确定39个专有代码库文件的健康水平。
    他们发现，在低质量代码中解决问题所需的时间是高质量代码的两倍多，而且低质量代码的缺陷密度高出15倍。
</p>
</section>
</div>

<div class="appendix">
<details id="SignificantRevisions">
<summary>Significant Revisions</summary>

<p><i>29 May 2019: </i>published</p>
</details>
</div>
</main>

<nav id="bottom-navmenu" style="display: none;">
<nav class="navmenu">
<div class="nav-head">  <div class="search">
    <!-- SiteSearch Google -->
    <form method="GET" action="https://www.google.com/search">
      <input type="hidden" name="ie" value="UTF-8">
      <input type="hidden" name="oe" value="UTF-8">
      <input class="field" type="text" name="q" size="15" maxlength="255">
      <button class="button" type="submit" name="btnG" value=" " title="Search">
      <input type="hidden" name="domains" value="martinfowler.com">
      <input type="hidden" name="sitesearch" value=""> 
      <input type="hidden" name="sitesearch" value="martinfowler.com">
    
  </button></form></div>

<div class="closediv">
<span class="close" title="close"></span>
</div>
</div>

<div class="nav-body">
<div class="topics">
<h2>Topics</h2>

<p><a href="https://martinfowler.com/architecture">Architecture</a></p>

<p><a href="https://refactoring.com/">Refactoring</a></p>

<p><a href="https://martinfowler.com/agile.html">Agile</a></p>

<p><a href="https://martinfowler.com/delivery.html">Delivery</a></p>

<p><a href="https://martinfowler.com/microservices">Microservices</a></p>

<p><a href="https://martinfowler.com/data">Data</a></p>

<p><a href="https://martinfowler.com/testing">Testing</a></p>

<p><a href="https://martinfowler.com/dsl.html">DSL</a></p>
</div>

<div class="about">
<h2>about me</h2>

<p><a href="https://martinfowler.com/aboutMe.html">About</a></p>

<p><a href="https://martinfowler.com/books">Books</a></p>

<p><a href="https://martinfowler.com/faq.html">FAQ</a></p>
</div>

<div class="content">
<h2>content</h2>

<p><a href="https://martinfowler.com/videos.html">Videos</a></p>

<p><a href="https://martinfowler.com/tags">Content Index</a></p>

<p><a href="https://martinfowler.com/articles/eurogames">Board Games</a></p>

<p><a href="https://martinfowler.com/photos">Photography</a></p>
</div>

<div class="tw">
<h2>Thoughtworks</h2>

<p><a href="https://thoughtworks.com/insights">Insights</a></p>

<p><a href="https://thoughtworks.com/careers">Careers</a></p>

<p><a href="https://thoughtworks.com/products">Products</a></p>
</div>

<div class="feeds">
<h2>follow</h2>

<p><a href="https://www.twitter.com/martinfowler">Twitter</a></p>

<p><a href="https://martinfowler.com/feed.atom">RSS</a></p>

<p><a href="https://toot.thoughtworks.com/@mfowler">Mastodon</a></p>
</div>
</div>
</nav>
</nav>
<footer id="page-footer">
<div class="tw-logo">
<a href="http://www.thoughtworks.com/">
<img src="../thoughtworks_white.png">
</a>
</div>
<div class="menu-button">
<div class="icon-bars navmenu-button"></div>
</div>
<div class="copyright">
<p>© Martin Fowler | <a href="http://www.thoughtworks.com/privacy-policy">Privacy Policy</a> | <a href="https://martinfowler.com/aboutMe.html#disclosures">Disclosures</a></p>
</div>
</footer>
<!-- Google Analytics -->
<!-- old Google Universal -->
<script>
window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)};ga.l=+new Date;
ga('create', 'UA-17005812-1', 'auto');
ga('send', 'pageview');
</script>
<script async="" src="../analytics.js"></script>
<!-- New Google GA4 -->
<!-- global site tag (gtag.js) - Google Analytics -->
<script async="" src="../js"></script>
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());

  gtag('config', 'G-6D51F4BDVF');
</script>
<!-- End Google Analytics -->



<script src="../jquery-1.11.3.min.js" type="text/javascript"></script>

<script src="../mfcom.js" type="text/javascript"></script>


</body><div id="transmart-crx-shadow-root" style="all: initial;"></div></html>